DEMO: Visualizing waves#
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, interactive
import scipy
from scipy.constants import physical_constants, hbar, h, c, k, m_e, Rydberg, e, N_A
%matplotlib inline
%config InlineBackend.figure_format='retina'
Standing and traveling waves in 1D#
We begin by plotting a simple periodic function using numpy (np) and matplotlib.pyplot (plt)
\[y = \sin(kx)=\sin\left(\frac{2\pi}{\lambda} x\right)\]
L=0.3 # Try different wavelengths
x = np.linspace(0.0, 1.0, 1000)
y = np.sin(2 * np.pi * x/L)
plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x1666eec40>]
By putting above example inside a python function will make wavelength exploration convenient
def wave(L=2):
x = np.linspace(0.0, 1.0, 1000)
y = np.sin(2*np.pi * x/L)
plt.plot(x, y, label=f'L={L}')
plt.xlabel('x')
plt.xlabel('y')
plt.legend()
plt.title('Sine waves')
plt.show()
# Change wavelength
wave(L=0.5)
Interact with waves#
By adding
@widgets.interact(parameters=(init,final))to our functions we can interactively parameters in the function using slider widgets.
interactive(wave, L=(0.1, 2))
Traveling, standing waves and wave interference#
def wavef2(k=10, t=0, phi=0, v=1):
x = np.linspace(0, 1., 1000)
wave1 = np.sin(k*(x-v*t))
wave2 = np.sin(k*(x-v*t)+phi) #try flipping the direction of velocity to get standing wave
plt.plot(x, wave1, lw=2, color='blue')
plt.plot(x, wave2, lw=2, color='green')
plt.plot(x, wave1+wave2, lw=3, color='red')
plt.ylim([-2.5, 2.5])
plt.legend(['Wave1','Wave2','Wave1+Wave2'])
plt.grid('on')
plt.show()
interactive(wavef2, k=(2, 20), t=(0,50.0,0.1), phi=(0, 2*np.pi, np.pi/8),v=1)
Traveling wave as a function of time and position#
import plotly.express as px
def wave_x_t(A = 1, k = 1.0, omega = 1, phi = 0):
# Create a grid of x and t values
x = np.linspace(0, 2 * np.pi, 50)
t = np.linspace(0, 2 * np.pi, 50)
X, T = np.meshgrid(x, t)
# Calculate the wave amplitude for each combination of x and t
Y = A * np.sin(k * X - omega * T + phi)
return px.scatter_3d(x=X.ravel(),
y=T.ravel(),
z=Y.ravel(),
color = Y.ravel(),
labels={'x': 'Position', 'y': 'Time', 'z': 'Amplitude'},
width=1000,
height=1000)
wave_x_t(A=1, k = 1.0, omega=2, phi=0)
Normal modes of 1D guitar string#
def wavef(n=1):
L=1
x = np.linspace(0, +1., 1000)
y = np.sin(n*np.pi * x/L)
plt.plot(x, y, lw=3)
plt.title(label=f'Normal mode # {n}')
plt.grid('--')
plt.show()
interactive(wavef, n=(1,20))
1D guitar vibrations as linear combination of normal modes#
For simplicity we will combine two modes with two different mode numbers and shifted with resepct to each ophter by a phase \(\phi\).
\[Mode_1 = cos(\omega t) \cdot sin(n_1\pi \cdot \frac{x}{L})\]
\[Mode_2 = cos(\omega t+\phi) \cdot sin(n_2\pi \cdot \frac{x}{L})\]
def wavef(n1=1, n2=1, phi=0,t=0):
L=1
omega=1
x = np.linspace(0, +1., 50)
mode1 = np.cos(omega*t) * np.sin(n1*np.pi * x/L)
mode2 = np.cos(omega*t + phi) * np.sin(n2*np.pi * x/L)
plt.plot(x, mode1+mode2, lw=5, color='orange')
plt.ylim([-2.5, 2.5])
plt.grid('on')
plt.show()
interactive(wavef, n1=(1,5), n2=(1,5), phi=(0,2*np.pi), t=(0,100,0.1) )
Normal modes of 2d membrane#
@interact(n=(1,10),m=(1,10))
def membrane(n=1, m=1):
# Constants
Lx, Ly = 1.0, 1.0 # Dimensions of the rectangular region
c = 1.0 # Wave speed
# Create a spatial grid
Nx, Ny = 100, 100
x, y = np.linspace(0, Lx, Nx), np.linspace(0, Ly, Ny)
X, Y = np.meshgrid(x, y)
# Compute spatial part of the normal mode
spatial_part = np.sin(m * np.pi * X / Lx) * np.sin(n * np.pi * Y / Ly)
fig, ax =plt.subplots()
ax.contourf(X, Y, spatial_part, 40, cmap='RdBu')
Vibrations of square 2D membrane as a linear combination of normal modes#
def membrane(n1=1, m1=1, n2=1, m2=1, t=0):
omega=1
L=1 # size of membrane
N=40 # number of grid points along X and Y
x = np.linspace(0,L,N)
y = np.linspace(0,L,N)
X,Y = np.meshgrid(x,y) # create 2D mesh of points along X and Y
mode1 = np.cos(omega*t) * np.sin(n1*np.pi*X/L) * np.sin(m1*np.pi*Y/L)
mode2 = np.cos(omega*t) * np.sin(n2*np.pi*X/L) * np.sin(m2*np.pi*Y/L)
fig, ax = plt.subplots(figsize=(9,6))
ax = plt.axes(projection='3d') # Making a 3D plot
ax.set_zlim([-2.0, 2.0])
ax.plot_surface(X, Y, mode1+mode2, cmap='RdYlBu') #Do the Plot
plt.show()
interactive(membrane, n1=(1,10), m1=(1,10), n2=(1,10), m2=(1,10), t=(0,100))
import holoviews as hv
from holoviews import opts
hv.extension('plotly')
def wave_mode(n, m):
'''Function to compute the 2D mode shapes'''
L = 1.0 # Side length
x, y = np.linspace(0, L, 100), np.linspace(0, L, 100)
X, Y = np.meshgrid(x, y)
mode_xy = np.sin(n * np.pi / L * X) * np.sin(m * np.pi / L * Y)
return hv.Surface(mode_xy)
# Create a HoloMap containing the mode shapes
holomap = hv.HoloMap({(n, m): wave_mode(n, m) for n in range(1,10) for m in range(1,10)}, kdims=['n', 'm'])
holomap.opts(opts.Surface(cmap='viridis', colorbar=True, width=900, height=900))